package com.athena.socket
{
	import com.adobe.serialization.json.JSON;
	import com.athena.controller.Handle;
	import com.athena.Objects.GameObject;
	import com.athena.Objects.PlayerObject;
	import com.athena.Objects.SystemSetting;
	import com.athena.utils.QueryString;
	import com.athena.utils.Util;
	import com.cubeia.firebase.connector.FirebaseClient;
	import com.cubeia.firebase.events.*;
	import com.cubeia.firebase.io.protocol.CreateTableResponsePacket;
	import com.cubeia.firebase.io.protocol.GameTransportPacket;
	import com.cubeia.firebase.io.protocol.JoinRequestPacket;
	import com.cubeia.firebase.io.protocol.JoinResponsePacket;
	import com.cubeia.firebase.io.protocol.LeaveResponsePacket;
	import com.cubeia.firebase.io.protocol.ServiceTransportPacket;
	import com.cubeia.firebase.io.protocol.TableSnapshotListPacket;
	import com.cubeia.firebase.io.ProtocolObject;
	import com.junkbyte.console.Cc;
	import flash.external.ExternalInterface;
	import flash.utils.ByteArray;
	
	/**
	 * ...
	 * @author chau
	 */
	public class CustomSocket extends FirebaseClient {
		private static var _instance:CustomSocket;
		private var oldAddressLobby:String = "";
		private var newAddressLobby:String = "";
		
		public function CustomSocket(host:String = null, port:String = null) {
			if (_instance) {
				throw new Error("Singleton... use getInstance()");
			}
			_instance = this;
			
			addEventListener(ConnectEvent.CONNECT, onFirebaseConnect);
			_instance.addEventListener(DisconnectEvent.DISCONNECT, onFirebaseDisconnect);
			_instance.addEventListener(LoginResponseEvent.LOGIN, onFirebaseLogin);
			_instance.addEventListener(PacketEvent.PACKET_RECEIVED, onPacketReceived);
			_instance.addEventListener(GamePacketEvent.PACKET_RECEIVED, onGamePacketReceived);
			open(host, port);
		}
		
		public static function getInstance():CustomSocket {
			return _instance;
		}
		
		private function onFirebaseConnect(connectEvent:ConnectEvent):void {
			removeEventListener(ConnectEvent.CONNECT, onFirebaseConnect);
			var obUser:Object = new Object();
			obUser.Userid = Main.getInstance().loginObject.UserId;
			obUser.Username = Main.getInstance().loginObject.Username;
			obUser.From = Main.getInstance().loginObject.From;
			obUser.gameid = Main.getInstance().gameObject.GAMEID;
			obUser.Signid = Main.getInstance().loginObject.Signid;
			login(JSON.encode(obUser), Main.getInstance().loginObject.sessionId, Main.getInstance().loginObject.operator);
		}
		
		private function onFirebaseDisconnect(disconnectEvent:DisconnectEvent):void {
			Util.simpleAlert("Bạn bị đứt kết nối với máy chủ");
		}
		
		private function onFirebaseLogin(loginEvent:LoginResponseEvent):void {
			try
			{
				if (loginEvent.getPlayerInfo().code == 0) {
					Main.getInstance().currPlayer = new PlayerObject(loginEvent.getPlayerInfo().pid);
					
					var ob:Object = new Object();
					ob.evt = "selectG";
					ob.gameid = Main.getInstance().gameObject.GAMEID;
					sendService(JSON.encode(ob));
					
				} else if (loginEvent.getPlayerInfo().code == -1) {
					Util.simpleAlert("Tài khoản đang được sử dụng !");
				}
				else if (loginEvent.getPlayerInfo().code == -2) {
					/*var __uri : String = ExternalInterface.call("geturl");
					   var qr : QueryString = new QueryString(__uri);
					 Util.navigateUrl("http://login.me.zing.vn/?url=" + encodeURI("http://me.zing.vn/apps/game-binh" + qr.getQueryString), "_self");*/
					Util.simpleAlert("zing me");
				}
				else if (loginEvent.getPlayerInfo().code == -4) {
					Util.simpleAlert("Tài khoản bạn đang bị khóa, liên hệ với Admin để được trợ giúp!");
				} else {
					Util.simpleAlert("Kết nối máy chủ gặp vấn đề, Hãy thử xóa cache rồi vào lại !");
				}
			} catch (e:Error) {
				Cc.log(e + "onFirebaseLogin");
			}
		}
		
		private function onPacketReceived(packetEvent:PacketEvent):void {
			var protocolObject:ProtocolObject = packetEvent.getObject();
			switch (protocolObject.classId()) {
				case JoinResponsePacket.CLASSID: 
					handleJoinResponsePacket(JoinResponsePacket(protocolObject));
					break;
				case ServiceTransportPacket.CLASSID: 
					handleServiceTransportPacket(ServiceTransportPacket(protocolObject));
					break;
				case CreateTableResponsePacket.CLASSID: 
					handleCreateTableResponsePacket(CreateTableResponsePacket(protocolObject));
					break;
				case LeaveResponsePacket.CLASSID: 
					Main.getInstance().gameObject.TABLEID = 0;
					Main.getInstance().gameObject.CREATE_TABLE = new Array();
					break;
				case TableSnapshotListPacket.CLASSID: 
					var arr:Array = TableSnapshotListPacket(protocolObject).snapshots;
					handleSnapshotListPacket(arr);
					removeLobby();
					break;
				default: 
					break;
			}
		}
		
		public function handleSnapshotListPacket(_arr:Array):void {
			var _arrTable:Array = new Array();
			for (var j:int = 0; j < _arr.length; j++) {
				var _obj:Object = new Object();
				_obj.capa = _arr[j].capacity;
				_obj.Id = _arr[j].tableid;
				//_obj.Seated = _arr[j].seated;
				for (var i:int = 0; i < _arr[j].params.length; i++) {
					if (_arr[j].params[i].key == "N") {
						_obj.N = (_arr[j].params[i].value as ByteArray).readUTF();
					} else if (_arr[j].params[i].key == "ArrN") {
						_arr[j].params[i].value.position = 0;
						_obj.ArrN = JSON.decode((_arr[j].params[i].value as ByteArray).readUTF());
							//Cc.log(_obj.ArrN);
					} else if (_arr[j].params[i].key == "M") {
						_arr[j].params[i].value.position = 0;
						_obj.M = _arr[j].params[i].value.readInt();
					} else if (_arr[j].params[i].key == "T") {
						_obj.T = _arr[j].params[i].value.readInt();
					} else if (_arr[j].params[i].key == "AG") {
						_obj.X = _arr[j].params[i].value.readInt();
					}
				}
				_obj.Seated = _obj.ArrN.length;
				if (Main.getInstance().gameObject.waitLobby && _obj.Seated < _obj.capa)
					_arrTable.push(_obj);
				else if (!Main.getInstance().gameObject.waitLobby)
					_arrTable.push(_obj);
			}
			var sortType:uint = (Main.getInstance().currPlayer.vip == 0) ? Array.NUMERIC : Array.DESCENDING;
			_arrTable.sortOn(["M", "Seated"], [Array.NUMERIC, sortType]);
			if (Main.getInstance().currPlayer.vip != 0)
				_arrTable.reverse();
			//add list table
			Main.getInstance().dashBoard.addListTable(_arrTable);
		}
		
		private function handleJoinResponsePacket(joinResponsePacket:JoinResponsePacket):void {
			if (joinResponsePacket.code == 0) {
				Main.getInstance().gameObject.TABLEID = joinResponsePacket.tableid;
			} else if (joinResponsePacket.code == -1) {
				Util.simpleAlert("Bàn đã hết chỗ trống. Bạn vui lòng chọn bàn khác !");
			} else if (joinResponsePacket.code == -2) {
				Util.simpleAlert("Bàn đã hủy. Bạn vui lòng chọn bàn khác !");
			} else if (joinResponsePacket.code == -3) {
				// popup nap tien
			} else if (joinResponsePacket.code == -4)
				Util.simpleAlert("Bạn đang ở trong bàn chơi");
			else if (joinResponsePacket.code == -5)
				Util.simpleAlert("Bàn đã bắt đầu ván !");
			else if (joinResponsePacket.code == -6)
				Util.simpleAlert("Bạn là người chơi mới nên không được đánh bàn có mức cược lớn !");
			else if (joinResponsePacket.code == -7)
				Util.simpleAlert("Cấp VIP của bạn không đủ để tham gia bàn chơi!");
			else if (joinResponsePacket.code == -8) {
				
					// popup nap tien
			}
		}
		
		private function handleServiceTransportPacket(serviceTransportPacket:ServiceTransportPacket):void {
			var data:ByteArray = serviceTransportPacket.servicedata;
			var bytes:int = data.bytesAvailable;
			var msg:String = data.readUTFBytes(bytes);
			Cc.log(msg);
			var decoded:Object = JSON.decode(msg);
			
			switch (decoded.evt) {
				case "13": 
					//Thong bao chuyen tien thanh cong
					break;
				case "10": 
					if (decoded.Cmd)
						Util.simpleAlert(decoded.Cmd);
					if (decoded.data)
						Util.simpleAlert(decoded.data);
					Util.removeLoad();
					break;
				case "0": 
					var obj:Object = JSON.decode(decoded.data);
					Main.getInstance().currPlayer.displayName = obj.Username;
					Main.getInstance().currPlayer.mark = obj.AG;
					Main.getInstance().currPlayer.gold = obj.LQ;
					Main.getInstance().currPlayer.vip = obj.VIP;
					Main.getInstance().currPlayer.loan = obj.AGVay;
					Main.getInstance().currPlayer.countMsg = obj.CMsg;
					Main.getInstance().currPlayer.pid = obj.Userid;
					
					Main.getInstance().dailyObject.OD = obj.OD;
					Main.getInstance().dailyObject.PD = obj.PD;
					Main.getInstance().gameObject.mailAutoOpen = obj.MT;
					
					Main.getInstance().currPlayer.userLQ = obj.UsernameLQ;
					Main.getInstance().currPlayer.register = obj.R;
					
					//ASBacay.currPlayer.TinyURL = obj.Tinyurl;
					//ASBacay.currPlayer.BigURL = Util.preTinyUrlBig + obj.Tinyurl + Util.sufTinyUrlBig;
					Main.getInstance().currPlayer.lock = obj.Pass;
					Main.getInstance().currPlayer.km = obj.X;
					Main.getInstance().currPlayer.gender = obj.G;
					if (Main.getInstance().currPlayer.register) {
						// show popup doi ten
					}
					// load vip 
					break;
				case "1": 
					break;
				case "2": 
					// load dashboard
					Main.getInstance().displayDashBoard(decoded.data);
					break;
				case "3": 
					break;
				case "4": 
					if (decoded.tableid == 0) {
						// show popup nap tien
					}
					else
						sendJoinTableRequest(decoded.tableid);
					break;
				case "5": 
					break;
				case "7": 
					Util.simpleAlert("Bạn được tặng " + Util.numberFormat(parseInt(decoded.data), 0) + " AG");
					//update tien
					break;
				case "8": 
					break;
				case "9": 
					break;
				case "11": 
					//friend
					break;
				case "16": 
					Main.getInstance().responeChat(decoded);
					break;
				case "15": 
					if (decoded.T == 10) {
						//ASBacay.dBoard.NewMail() ;	
					}
					break;
				case "20": 
					Main.getInstance().dashBoard.mailController.MailPlayerRespone(decoded, true);
					break;
				case "21": 
					Main.getInstance().dashBoard.mailController.MailPlayerRespone(decoded);
					break;
				case "22": 
					Main.getInstance().dashBoard.bankController.TransferMark(decoded.data);
					break;
				case "31": 
					Main.getInstance().dashBoard.bankController.getAGSuccess(decoded.AG);
					break;
				case "cv": 
					//LQAGFunction.LQAGConvert(decoded) ;
					//ASBacay.dBoard._ChangeLQClass.receiveChangeLQ(decoded);
					break;
				case "14": 
					if (decoded.T == "1") {
						//ASBacay.dBoard._BankClass.ResultLoanAG(decoded.data);
					} else if (decoded.T == "2") {
						//ASBacay.dBoard._BankClass.ResultPayAG();
					}
					break;
				case "12": 
					switch (decoded.T) {
						case "1": 
							Util.simpleAlert(decoded.data);
							break;
						case "2": 
							//ASBacay.dBoard._LockClass.UnLockWaitOK() ;
							break;
						case "5": 
							Util.simpleAlert(decoded.data);
							//ASBacay.dBoard.isOpenLock = true;
							//ASBacay.dBoard.loadDailyGift();
							//ASBacay.dBoard._LockClass.UnLockOK() ;
							break;
						case "7": 
							Util.simpleAlert(decoded.data);
							//ASBacay.dBoard._LockClass.DeleteLockOK() ;
							break;
						
					}
					break;
				case "dp": 
					//ASBacay.dBoard.updateAG(ASBacay.currPlayer.Mark + decoded.AG);
					//ASBacay.dBoard._DailyClass.close();
					//ASBacay.isMiniGame = false;
					//ASBacay.dBoard.AutoOpenMail();
					break;
				case "dg": 
					//ASBacay.dBoard._AuctionClass.AuctionOK(decoded);
					break;
				case "xs": 
					//ASBacay.dBoard._LotteryClass.LotteryOK(decoded) ;
					break;
				case "pf": 
					//ASBacay.dBoard._ProfileClass.Profile_OK();
					break;
				case "time": 
					//ASBacay.dBoard._LuckyClass.DisplayData(decoded);
					break;
				case "slucky": 
					//ASBacay.dBoard._LuckyClass.Result(decoded);
					break;
				case "flucky": 
					//ASBacay.dBoard._LuckyClass.LuckyAG(decoded);
					//LuckyCardFunction.LuckyAG(decoded) ;
					break;
				case "100": 
					//ASBacay.SpecialAlert(decoded.Cmd);
					//OtherFunction.SpecialAlert(decoded.Cmd) ;
					break;
				case "uvip": 
					//if (ASBacay.gBoard != null) {
					//ASBacay.gBoard.ShowUpVip(decoded.AG);
					//}
					break;
				case "rl": 
					//ASBacay.dBoard._RouletteClass.spin(decoded.id, decoded.N, decoded.LQ);
					break;
				case "frl": 
					//ASBacay.dBoard._RouletteClass.finish(decoded.AG);
					break;
				case "fb": 
					//ASBacay.dBoard._FootballClass.responeHandle(decoded);
					break;
				case "agtv": 
					//ASBacay.tf.appendText(JSON.encode(decoded));
					//ChuyenVipFunction.success(decoded);//M: vip , AG: ag
					break;
				case "ivp": 
					if (decoded.T == 1)
					{
						//if (ASBacay.gBoard == null) {
						//ASBacay.DisplayInvite(decoded);
						//}
					}
					else
					{
						//if (ASBacay.gBoard != null) {
						//ASBacay.gBoard.DisplayListInvite(decoded.data);
						//}
					}
					break;
				case "CULQ": 
					// data 1 0
					//ASBacay.changeNameClass.returnCheck(decoded);
					break;
				case "NRULQ": 
					// data 1 0
					//ASBacay.changeNameClass.returnAccept(decoded);
					break;
				case "selectR": 
					Main.getInstance().gameObject.ROOMID = Main.getInstance().dashBoard.rooms.id;
					Main.getInstance().dashBoard.removeRoom();
					addLobby();
					Util.removeLoad();
					break;
				case "SAON": 
					//ASBacay.SaleAlert(decoded.Cmd);
					break;
				case "SAOFF": 
					break;
				case "US": 
					Main.getInstance().sysSetting = new SystemSetting(decoded.data);
					break;
				case "salert": 
					//ASBacay.SpecialAlert(decoded.data);
					break;
			}
		}
		
		private function handleCreateTableResponsePacket(handle:CreateTableResponsePacket):void {
			if (handle.code == 1) {
				Cc.log("Bạn không đủ điểm để tạo bàn chơi");
					//show popup nap tien
			} else {
				Main.getInstance().gameObject.TABLEID = handle.tableid;
			}
		}
		
		public function sendJoinTableRequest(id:int):void {
			var joinRequestPacket:JoinRequestPacket = new JoinRequestPacket();
			joinRequestPacket.seat = -1;
			joinRequestPacket.tableid = id;
			send(joinRequestPacket);
		}
		
		private function onGamePacketReceived(gamePacketEvent:GamePacketEvent):void {
			var data:ByteArray = gamePacketEvent.getPacketData();
			var bytes:int = data.bytesAvailable;
			if (bytes == 0) return;
		
			var msg:String = data.readUTFBytes(bytes);
			Cc.log(msg);
			
			var objReceive:Object = JSON.decode(msg);
			
			switch (objReceive.evt){
				case "ctable": 
					Main.getInstance().handle.createTable(objReceive.data);
					break;
				case "stable": 
					Main.getInstance().handle.joinTable(objReceive.data);
					break;
				case "jtable": 
					Main.getInstance().handle.otherJoinTable(objReceive.data);
					break;
				case "rtable": 
					Main.getInstance().handle.readyTable(objReceive.Name);
					break;
				case "ltable": 
					Main.getInstance().handle.leaveTable(objReceive.Name);
					break;
				case "cctable": 
					Main.getInstance().handle.ccTable(objReceive.Name);
					break;
				case "vtable": 
					Main.getInstance().handle.vTable(objReceive.data);
					break;
				case "lc": 
					Main.getInstance().gameBoard.startGame(objReceive);
					break;
				case "cc": 
					break;
				case "cn": 
					break;
				case "dc": 
					break;
				case "cb": 
					break;
				case "pm": 
					break;
				case "pb": 
					break;
				case "lb": 
					break;
				case "fb": 
					break;
				case "pk": 
					break;
				case "finish": 
					break;
				case "am": 
					break;
				case "thongbao": 
					Util.simpleAlert(objReceive.Cmd);
					break;
				case "0": 
					Util.simpleAlert(objReceive.data);
					break;
				case "chattable": 
					break;
				case "schat": 
					break;
				case "setting": 
					break;
			}
		}
		
		public function addLobby():void {
			oldAddressLobby = newAddressLobby;
			newAddressLobby = "0/" + Main.getInstance().gameObject.ROOMID + "/";
			if (oldAddressLobby.length > 0)
				lobbyUnsubscribe(Main.getInstance().gameObject.GAMEID, oldAddressLobby);
			lobbySubscribe(Main.getInstance().gameObject.GAMEID, newAddressLobby);
		}
		
		public function removeLobby():void {
			lobbyUnsubscribe(Main.getInstance().gameObject.GAMEID, newAddressLobby);
		}
		
		public function sendData(str:String):void {
			var data:ByteArray = new ByteArray();
			data.writeUTFBytes(str);
			var gameTransportPacket:GameTransportPacket = new GameTransportPacket();
			gameTransportPacket.pid = Main.getInstance().currPlayer.pid;
			gameTransportPacket.tableid = Main.getInstance().gameObject.TABLEID;
			gameTransportPacket.gamedata = data;
			send(gameTransportPacket);
		}
		
		public function sendService(str:String):void {
			var servicePacket:ServiceTransportPacket = new ServiceTransportPacket();
			servicePacket.idtype = 1;
			servicePacket.pid = Main.getInstance().currPlayer.pid;
			servicePacket.seq = 1;
			servicePacket.service = "com.athena.services.api.ServiceContract";
			var data:ByteArray = new ByteArray();
			data.writeUTFBytes(str);
			servicePacket.servicedata = data;
			send(servicePacket);
		}
	}

}